package com.example.socket.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelOption;
import io.netty.util.concurrent.EventExecutorGroup;

import java.util.HashMap;
import java.util.Map;

/**
 * 执行器配置信息<br/>
 * 用于创建一个受配置的{@link ExecutorFilter}
 * @author frank
 */
public class SessionConfig {

    /** 是否允许重用地址 */
    public static final boolean REUSE_ADDR = true;
    /** 是否允许半开连接 */
    private boolean allowHalfClosure;
    /** 读缓冲 */
    private Integer readBuffSize;
    /** 写缓冲 */
    private Integer writeBuffSize;
    /** 连接超时 */
    private Integer timeout;
    /** 最大连接数 */
    private Integer backlog;
    /** TCP无延迟*/
    private boolean tcpNodelay;
    /** 池化buffer*/
    private boolean pooled;

    public static SessionConfig valueOfServer(int readBufferSize, int writeBuffSize, int timeout, int backlog, boolean tcpNodelay, boolean allowHalfClosure, boolean pooled) {
        SessionConfig result = new SessionConfig();
        result.readBuffSize = readBufferSize;
        result.writeBuffSize = writeBuffSize;
        result.timeout = timeout;
        result.backlog = backlog;
        result.tcpNodelay = tcpNodelay;
        result.allowHalfClosure = allowHalfClosure;
        result.pooled = pooled;
        return result;
    }

    public static SessionConfig valueOfClient(int readBufferSize, int writeBuffSize) {
        SessionConfig result = new SessionConfig();
        result.readBuffSize = readBufferSize;
        result.writeBuffSize = writeBuffSize;
        result.allowHalfClosure = false;
        return result;
    }

    /**
     * 创建 {@link EventExecutorGroup} 并返回
     * @return
     */
    public Map<ChannelOption<?>, ?> buildClient() {
        Map<ChannelOption<?>, Object> values = new HashMap<>();
        values.put(ChannelOption.SO_RCVBUF, readBuffSize);
        values.put(ChannelOption.SO_SNDBUF, writeBuffSize);
        // values.put(ChannelOption.SO_TIMEOUT, timeout);

        // 客户端默认选项
        values.put(ChannelOption.TCP_NODELAY, tcpNodelay);
        values.put(ChannelOption.ALLOW_HALF_CLOSURE, allowHalfClosure);
        return values;
    }

    /**
     * socket参数
     * @param connector
     */
    public void buildTcpServerOption(ServerBootstrap connector) {
        connector.option(ChannelOption.SO_BACKLOG, backlog);
        connector.option(ChannelOption.SO_REUSEADDR, REUSE_ADDR);

        connector.childOption(ChannelOption.SO_SNDBUF, writeBuffSize);
        connector.childOption(ChannelOption.SO_RCVBUF, readBuffSize);
        connector.childOption(ChannelOption.TCP_NODELAY, tcpNodelay);
        connector.childOption(ChannelOption.ALLOW_HALF_CLOSURE, allowHalfClosure);
        //使用池化buffer
        if (pooled) {
            connector.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
            connector.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
        }
    }

    // Getter and Setter ...

    public int getReadBufferSize() {
        return readBuffSize;
    }

    public int getWriteBuffSize() {
        return writeBuffSize;
    }

    public long getTimeout() {
        return timeout;
    }

    public int getBacklog() {
        return backlog;
    }

    public boolean isPooled() {
        return pooled;
    }

    public void setPooled(boolean pooled) {
        this.pooled = pooled;
    }
}
